﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
using System.IO;
using OfficeOpenXml;
using System.Timers;
using AutomatedMedicalDetection.utils;

namespace AutomatedMedicalDetection
{
    public partial class form : Form
    {
        private string machine_cpu;
        private string temperature;
        private string temperature_10;
        private TcpClient client;
        private NetworkStream stream;
        private DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        private List<String> analyzeStr = new List<string>();
        private Dictionary<string, string> instrumentConfigurationMap = new Dictionary<string, string>();


        private static System.Timers.Timer timer;
        //自增序号
        private int index = 0;
        //是否调零
        private int is_zeroAdjustment = 0;
        //是否读吸光
        private int is_readingAbsorbance = 1;
        //程序计数器
        private static uint TM = 0;
        private static System.Timers.Timer timer_TM;

        public form(TcpClient clientDTO, NetworkStream streamDTO)
        {
            client = clientDTO;
            stream = streamDTO;
            InitializeComponent();
            //初始化仪器配置
            InitialConfiguration();
            //开启程序计数器
            SettingsProgramCount();
        }
        //========================================================初始化加载=========================================================
        //初始化获取机器时间
        private void InitialConfiguration()
        {
            string projectRootPath = AppDomain.CurrentDomain.BaseDirectory;
            projectRootPath = projectRootPath.Substring(0, projectRootPath.LastIndexOf("bin"));
            string jsonFilePath = Path.Combine(projectRootPath, "InstrumentConfiguration.json");
            instrumentConfigurationMap = Util.ReadDeviceInfoAsMap(jsonFilePath);
            if (instrumentConfigurationMap != null)
            {
                instrument_box.Items.Clear();
                foreach (var kvp in instrumentConfigurationMap)
                {
                    instrument_box.Items.Add(kvp.Key);
                }
                if (instrument_box.Items.Count > 0)
                {
                    instrument_box.SelectedIndex = 0; // Set default selection to the first item
                }
            }
            else
            {
                MessageBox.Show("Failed to load devices.");
            }
        }
        //启动异步监听获取机器返回
        public async void BeginReadData()
        {
            byte[] buffer = new byte[1024];
            int bytesRead;
            try
            {
                while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0)
                {
                    string responseData = BitConverter.ToString(buffer, 0, bytesRead).Replace("-", " ");
                    //截取命令类型
                    string subString = responseData.Substring(18, 23 - 18).Replace(" ", "");
                    //截取返回信息
                    string str = responseData.Substring(23, (responseData.Length - 2) - 23);
                    //判断命令类型
                    switch (subString)
                    {
                        case "5200":
                            time_lab.Text = ParseTimestamp(str).ToString();
                            break;
                        case "C000":
                            HeartbeatAnalysis(str);
                            break;
                        case "8300":
                            AnalyzeUInt16Array(str);
                            break;
                        case "8400":
                            AnalyzeByteArray(str);
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("读取数据时出错: " + ex.Message);
            }
        }
        //定时任务设置器
        private void SetDailyTimer()
        {
            timer = new System.Timers.Timer();
            timer.Interval = GetNextInterval();
            timer.Elapsed += OnTimedEvent;
            timer.AutoReset = false;
            timer.Enabled = true;
        }
        private static double GetNextInterval()

        {
            DateTime now = DateTime.Now;
            DateTime nextMidnight = now.Date.AddDays(1);
            return (nextMidnight - now).TotalMilliseconds;
        }
        //定时任务 00：00
        public void OnTimedEvent(Object source, ElapsedEventArgs e)
        {
            try
            {
                string projectRootPath = AppDomain.CurrentDomain.BaseDirectory;
                projectRootPath = projectRootPath.Substring(0, projectRootPath.LastIndexOf("bin"));
                string tempDirPath = Path.Combine(projectRootPath, "data", "temporarily", machine_cpu);
                string historyDirPath = Path.Combine(projectRootPath, "data", "history", machine_cpu);

                // 创建历史目录（如果不存在）
                Directory.CreateDirectory(historyDirPath);

                // 获取 machine_cpu 下的所有子文件夹
                if (Directory.Exists(tempDirPath))
                {
                    string[] subFolders = Directory.GetDirectories(tempDirPath);
                    foreach (string subFolder in subFolders)
                    {
                        string folderName = Path.GetFileName(subFolder);
                        string newFolderPath = Path.Combine(historyDirPath, folderName);
                        // 移动子文件夹到历史目录
                        Directory.Move(subFolder, newFolderPath);
                        Console.WriteLine($"Moved {subFolder} to {newFolderPath}");
                    }
                }
                else
                {
                    Console.WriteLine($"No directory found for {tempDirPath}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error while moving folders: " + ex.Message);
            }

            // 重新设置定时器，以便它在下一次00:00时再次触发
            timer.Interval = GetNextInterval();
            timer.Start();
        }

        //设置程序计数器
        private void SettingsProgramCount()
        { 
            // 初始化计数器
            TM = 0;
            // 设置定时器，每20毫秒触发一次
            timer_TM = new System.Timers.Timer(20);
            timer_TM.Elapsed += ProgramCount;
            timer_TM.AutoReset = true;
            timer_TM.Enabled = true;
        }
        //定时计数器
        private static void ProgramCount(Object source, ElapsedEventArgs e)
        {
            // 每次触发事件时，计数器加1
            TM++;

            // 将32位计数器TM拆分成4个字节
            byte tm0 = (byte)(TM & 0xFF);        // 最低位
            byte tm1 = (byte)((TM >> 8) & 0xFF);
            byte tm2 = (byte)((TM >> 16) & 0xFF);
            byte tm3 = (byte)((TM >> 24) & 0xFF); // 最高位

            // 显示当前时间和计数器值
            string currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
            Console.WriteLine($"时间: {currentTime}, 计数器值: {TM} (TM3: {tm3}, TM2: {tm2}, Tms: {tm1}, TmO: {tm0})");
        }

        //========================================================命令按钮=========================================================
        //连接仪器
        private void btnConnect_Click(object sender, EventArgs e)
        {
            string instrumentConfigurationStr=instrumentConfigurationMap[instrument_box.Text];
            string []str= instrumentConfigurationStr.Split(':');
            string ipAddress = str[0];
            int port = int.Parse(str[1]);
            try
            {
                client = new TcpClient(ipAddress, port);
                stream = client.GetStream();
                connectStatus_lab.Text = "成功";
                
                //启动异步监听
                BeginReadData();
                Thread.Sleep(500);
                //设置启动定时任务
                SetDailyTimer();
                Thread.Sleep(500);
                //启动校验一次机器时间
                verificationTime_but.PerformClick();
                Thread.Sleep(500);
                //初始化获取机器时间
                AcquisitionTime();
                //获取机器心跳
                Thread.Sleep(500);
                HeartbeatInfo();

                MessageBox.Show("连接成功: ");
            }
            catch (Exception ex)
            {
                MessageBox.Show("连接失败" + ex.Message);
            }
        }
        //初始化获取机器时间
        private void AcquisitionTime()
        {
            string hexCommand = "23 31 32 33 34 41 5200"; // 示例十六进制指令
            SendHexCommand(hexCommand);
        }
        //校验时间
        private void verificationTime_but_Click(object sender, EventArgs e)
        {
            string hexTime = GetCurrentTimeAsHex();
            string hexCommand = "23 31 32 33 34 41 5300 " + hexTime; // 示例十六进制指令
            SendHexCommand(hexCommand);
            AcquisitionTime();
        }


        //获取机器心跳
        private void HeartbeatInfo() {
            string hexCommand = "23 31 32 33 34 41 C000"; // 示例十六进制指令
            SendHexCommand(hexCommand);
        }

        //比色杯调零
        private void zeroAdjustment_but_Click(object sender, EventArgs e)
        {
            string hexCommand = "23 31 32 33 34 41 8300"; // 示例十六进制指令
            SendHexCommand(hexCommand);
        }
        //读吸光度
        private void readingAbsorbance_but_Click(object sender, EventArgs e)
        {
            if (is_zeroAdjustment==0) {
                MessageBox.Show("请先执行调零程序!");
                return;
            }
            string hexCommand = "23 31 32 33 34 41 8400"; // 示例十六进制指令
            SendHexCommand(hexCommand);
        }
        //上升
        private void rise_but_Click(object sender, EventArgs e)
        {
            string hexCommand = "23 31 32 33 34 41 24 00 03 C0"; // 示例十六进制指令
            SendHexCommand(hexCommand);
        }
        //到零点
        private void descend_but_Click(object sender, EventArgs e)
        {
            string hexCommand = "23 31 32 33 34 41 21 01"; // 示例十六进制指令
            SendHexCommand(hexCommand);
        }
        //针下底
        private void underfloor_but_Click(object sender, EventArgs e)
        {
            string hexCommand = "23 31 32 33 34 41 26 01"; // 示例十六进制指令
            SendHexCommand(hexCommand);
        }
        //急停
        private void scram_but_Click(object sender, EventArgs e)
        {
            string hexCommand = "23 31 32 33 34 41 2500"; // 示例十六进制指令
            SendHexCommand(hexCommand);
        }
        //旋转到0号位置
        private void rotate0_but_Click(object sender, EventArgs e)
        {
            string hexCommand = "23 31 32 33 34 41 31 00"; // 示例十六进制指令
            SendHexCommand(hexCommand);
        }
        //急停
        private void rotate1_but_Click(object sender, EventArgs e)
        {
            string hexCommand = "23 31 32 33 34 41 35 00"; // 示例十六进制指令
            SendHexCommand(hexCommand);
        }
        //旋转到8号杯
        private void rotate8_but_Click(object sender, EventArgs e)
        {
            string hexCommand = "23 31 32 33 34 41 38 00 08"; // 示例十六进制指令
            SendHexCommand(hexCommand);
        }
        //吸液
        private void suction_but_Click(object sender, EventArgs e)
        {
            string hexCommand = "23 31 32 33 34 41 4e 01 01 40"; // 示例十六进制指令
            SendHexCommand(hexCommand);
        }
        //吐液
        private void spittingLiquid_but_Click(object sender, EventArgs e)
        {
            string hexCommand = "23 31 32 33 34 41 49 01"; // 示例十六进制指令
            SendHexCommand(hexCommand);
        }










        //========================================================数据处理,展示保存=========================================================
        private ushort[] ReturnHexStringToUInt16Array(string hex)
        {
            // 移除字符串中的所有空格
            hex = hex.Replace(" ", "");

            // 检查字符串长度是否为4的倍数
            if (hex.Length % 4 != 0)
            {
                throw new ArgumentException("Hex string must have a length that is a multiple of 4");
            }

            // 创建 ushort 数组
            ushort[] values = new ushort[hex.Length / 4];

            // 循环遍历字符串，每四个字符转换为一个 ushort
            for (int i = 0; i < hex.Length; i += 4)
            {
                string str = hex.Substring(i, 4);
                values[i / 4] = Convert.ToUInt16(str, 16);
            }
            return values;
        }
        private ushort[] ReturnHexStringToByteArray(string hex)
        {
            // 移除字符串中的所有空格
            hex = hex.Replace(" ", "");
            // 检查字符串长度是否为偶数
            if (hex.Length % 2 != 0)
            {
                throw new ArgumentException("Hex string must have an even length");
            }
            // 创建字节数组
            ushort[] bytes = new ushort[hex.Length / 2];
            // 循环遍历字符串，每两个字符转换为一个字节
            for (int i = 0; i < hex.Length; i += 2)
            {
                string str = hex.Substring(i, 2);
                bytes[i / 2] = Convert.ToUInt16(str, 16);
            }
            return bytes;
        }


        private byte[] HexStringToByteArray(string hex)
        {
            hex = hex.Replace(" ", ""); // Remove any spaces in the hex string
            byte[] bytes = new byte[hex.Length / 2];
            for (int i = 0; i < hex.Length; i += 2)
            {
                bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
            }
            return bytes;
        }



        private void SendHexCommand(string hexCommand)
        {
            if (client != null && client.Connected)
            {
                try
                {
                    byte[] data = HexStringToByteArray(hexCommand);
                    stream.Write(data, 0, data.Length);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("发送命令时出错: " + ex.Message);
                }
            }
            else
            {
                MessageBox.Show("连接已断开，请重新连接!");
            }
        }
        private void AnalyzeUInt16Array(string hexMessage)
        {
            try
            {
                // 清空DataGridView的行
                this.value_dgv.Rows.Clear();

                // 将16进制字符串转换为字节数组
                ushort[] timestampBytes = ReturnHexStringToUInt16Array(hexMessage);

                // 加载数据
                // 固定值的数组
                string[] tubes = { "αADC", "βADC", "γADC", "δADC", "αPWM", "βPWM", "γPWM", "δPWM" };

                // 从下标 24 开始，每行依次 6 个值
                int startIndex = 0;
                for (int i = 0; i < tubes.Length; i++)
                {
                    // 创建一行数据
                    string[] row = new string[7];
                    row[0] = tubes[i]; // 试管列
                    for (int j = 0; j < 6; j++)
                    {
                        if (startIndex + i * 6 + j < timestampBytes.Length)
                        {
                            row[j + 1] = timestampBytes[startIndex + i * 6 + j].ToString(); // 将 ushort 值转换为十六进制字符串
                        }
                    }
                    this.value_dgv.Rows.Add(row);
                }
                time_but.Text= timestampBytes[timestampBytes.Length-1].ToString();
                //保存历史记录
                saveAnalyzeUInt16Array(timestampBytes, machine_cpu, temperature_10, "调零", time_but.Text);
                //记录程序已经调零
                is_zeroAdjustment = 1;
                is_readingAbsorbance = 0;
            }
            catch (Exception ex)
            {
                MessageBox.Show("解析时间戳时出错: " + ex.Message);
            }
        }
        private void AnalyzeByteArray(string hexMessage)
        {
            try
            {
                // 清空DataGridView的行
                this.value_dgv.Rows.Clear();
                // 将16进制字符串转换为字节数组
                ushort[] timestampBytes = ReturnHexStringToByteArray(hexMessage);

                // 加载数据
                // 固定值的数组
                string[] tubes = { "α", "β", "γ", "δ" };

                // 只取奇数下标的值
                timestampBytes = FilterOddIndexValues(timestampBytes);

                // 从下标 0 开始，每行依次 6 个值
                for (int i = 0; i < tubes.Length; i++)
                {
                    // 创建一行数据
                    string[] row = new string[7];
                    row[0] = tubes[i]; // 试管列
                    for (int j = 0; j < 6; j++)
                    {
                        int index = i * 6 + j;
                        if (index < timestampBytes.Length)
                        {
                            row[j + 1] = timestampBytes[index].ToString(); // 将 ushort 值转换为十六进制字符串
                        }
                    }
                    this.value_dgv.Rows.Add(row);
                }
                string str = hexMessage.Substring(hexMessage.Length-6).Replace(" ", ""); ;
                ushort bey = Convert.ToUInt16(str, 16);
                time_but.Text = timestampBytes[timestampBytes.Length - 1].ToString();

                // 将数据写入到 Excel 中
                saveAnalyzeUInt16Array(timestampBytes, machine_cpu, temperature_10,"读吸光", time_but.Text);
                //记录程序已经测吸光度
                is_readingAbsorbance = 1;
            }
            catch (Exception ex)
            {
                MessageBox.Show("解析时间戳时出错: " + ex.Message);
            }
        }
        private ushort[] FilterOddIndexValues(ushort[] values)
        {
            int count = values.Length / 2;
            ushort[] result = new ushort[count];
            for (int i = 0, j = 1; i < count; i++, j += 2)
            {
                result[i] = values[j];
            }
            return result;
        }

        //解析时间
        private DateTime ParseTimestamp(string hexMessage)
        {
            try
            {
                // 将16进制字符串转换为字节数组
                byte[] timestampBytes = HexStringToByteArray(hexMessage);
                Array.Reverse(timestampBytes); // 如果字节序是大端，需要反转字节数组
                uint seconds = BitConverter.ToUInt32(timestampBytes, 0);
                // 计算时间戳
                DateTime dateTime = epoch.AddSeconds(seconds).ToLocalTime();
                return dateTime;
            }
            catch (Exception ex)
            {
                MessageBox.Show("解析时间戳时出错: " + ex.Message);
                return DateTime.MinValue;
            }
        }
        public static string GetCurrentTimeAsHex()
        {
            // 获取当前系统时间的整数表示（Unix时间戳）
            uint currentTime = (uint)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;

            // 将uint类型的时间戳转换为十六进制字符串，每两位添加一个空格
            string hexString = currentTime.ToString("X");
            hexString = InsertSpaces(hexString, 2); // 每两位添加一个空格

            return hexString;
        }

        private static string InsertSpaces(string str, int interval)
        {
            // 从后往前插入空格
            for (int i = str.Length - interval; i > 0; i -= interval)
            {
                str = str.Insert(i, " ");
            }
            return str;
        }
        //解析心跳参数,温度,机器
        public void HeartbeatAnalysis(string str)
        {
            // 打印固定数据，获取机器cpu
            machine_cpu = str.Substring(0,36);
            string temperatureStr = str.Substring(49, 5);
            
            if (temperatureStr == "FF FF") {
                temperature = "0";
            }
            temperature_10 = Convert.ToUInt16(temperatureStr.Replace(" ",""), 16).ToString();
            temperature_lab.Text = "环境温度: " + temperature + " °C";
        }
        //保存历史记录
        private void saveAnalyzeUInt16Array(ushort[] data, string machineCpu, string temperature,string type,string time) {
            try
            {
                index++;
                // 获取项目根目录
                string projectRootPath = AppDomain.CurrentDomain.BaseDirectory;
                projectRootPath = projectRootPath.Substring(0, projectRootPath.LastIndexOf("bin"));
                // 设置路径
                string datePath = DateTime.Now.ToString("yyyyMMdd");
                string directoryPath = Path.Combine(projectRootPath, "data", "temporarily", machineCpu, datePath);
                string filePath = Path.Combine(directoryPath, "数据列表.xlsx");
                // 创建目录（如果不存在）
                Directory.CreateDirectory(directoryPath);
                // 设置EPPlus的许可证上下文
                ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;

                // 创建Excel文件或打开已有的Excel文件
                FileInfo fileInfo = new FileInfo(filePath);
                using (ExcelPackage package = new ExcelPackage(fileInfo))
                {
                    ExcelWorksheet worksheet;
                    // 检查 type 是否为 "调零"，如果是则新建一个工作表
                    if (type == "调零" && is_readingAbsorbance==1)
                    {
                        index = 1;
                        worksheet = package.Workbook.Worksheets.Add("检测_" + DateTime.Now.ToString("HHmmss"));
                        // 设置标头
                        string[] headers = { "序号", "数据类型", "仪器时间", "系统时间", "备注", "温度", "Ⅰα", "Ⅱα", "IIIα", "IVα", "Vα", "VIα", "Ⅰβ", "Ⅱβ", "IIIβ", "IVβ", "Vβ", "VIβ", "Ⅰγ", "Ⅱγ", "IIIγ", "IVγ", "Vγ", "VIγ", "Ⅰδ", "Ⅱδ", "IIIδ", "IVδ", "Vδ", "VIδ" };
                        for (int i = 0; i < headers.Length; i++)
                        {
                            worksheet.Cells[1, i + 1].Value = headers[i];
                        }
                    }
                    else
                    {
                        // 如果工作表已存在，则打开它；否则，创建新工作表
                        if (package.Workbook.Worksheets.Count > 0)
                        {
                            worksheet = package.Workbook.Worksheets[package.Workbook.Worksheets.Count-1];
                        }
                        else
                        {
                            worksheet = package.Workbook.Worksheets.Add("检测_" + DateTime.Now.ToString("HHmmss"));
                            // 设置标头
                            string[] headers = { "序号", "数据类型", "仪器时间", "系统时间", "备注", "温度", "Ⅰα", "Ⅱα", "IIIα", "IVα", "Vα", "VIα", "Ⅰβ", "Ⅱβ", "IIIβ", "IVβ", "Vβ", "VIβ", "Ⅰγ", "Ⅱγ", "IIIγ", "IVγ", "Vγ", "VIγ", "Ⅰδ", "Ⅱδ", "IIIδ", "IVδ", "Vδ", "VIδ" };
                            for (int i = 0; i < headers.Length; i++)
                            {
                                worksheet.Cells[1, i + 1].Value = headers[i];
                            }
                        }
                    }
                    // 获取数据的起始行
                    int startRow = worksheet.Dimension?.End.Row ?? 1;
                    int currentRow = startRow + 1;

                    // 写入数据到Excel
                    int numRows = (data.Length + 23) / 24; // 每24个值分一行
                    for (int row = 0; row < numRows; row++)
                    {
                        int startIndex = row * 24;
                        int endIndex = Math.Min(startIndex + 24, data.Length);

                        if (endIndex - startIndex < 24)
                        {
                            // 如果当前行数据不足24个值，则跳过这一行
                            continue;
                        }
                        //worksheet.Cells[currentRow, 1].Value = row == 0 ? index+"a" : index+"p"; // 自增序号
                        worksheet.Cells[currentRow, 1].Value = index; // 自增序号
                        if (type == "调零")
                        {
                            worksheet.Cells[currentRow, 2].Value = row == 0 ? "99" : "98"; // 自增序号
                        }
                        else if (type == "读吸光") {
                            worksheet.Cells[currentRow, 2].Value = "0"; // 自增序号
                        }
                        worksheet.Cells[currentRow, 3].Value = time; // 仪器时间
                        worksheet.Cells[currentRow, 4].Value = DateTime.Now.ToString("HH:mm:ss"); // 系统时间
                        worksheet.Cells[currentRow, 5].Value = ""; // 备注
                        worksheet.Cells[currentRow, 6].Value = temperature; // 温度

                        for (int col = 0; col < 24; col++)
                        {
                            int index = startIndex + col;
                            if (index < data.Length)
                            {
                                worksheet.Cells[currentRow, col + 7].Value = data[index];
                            }
                        }
                        currentRow++;
                    }
                    // 保存Excel文件
                    package.Save();
                }
            }
            catch (Exception ex)
            {
                // 错误处理
                MessageBox.Show("保存数据到Excel时出错: " + ex.Message);
            }
        }

        //========================================================组件判断=========================================================
        //点击跳转页面判断
        private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
        {
            TabControl tabControl = sender as TabControl;
            if (tabControl != null)
            {
                TabPage selectedTab = tabControl.SelectedTab;
                // 在这里进行你的判断逻辑
                if (selectedTab.Text == "检测")
                {
                    if (client != null && client.Connected)
                    {

                    }
                    else
                    {
                        tabControl.SelectTab(0);
                        MessageBox.Show("未连接仪器，请先连接!");
                    }
                }
            }
        }








        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            if (client != null)
            {
                stream.Close();
                client.Close();
            }
        }

        private void CESHI1_Click(object sender, EventArgs e)
        {
            // 启动并测试定时任务
            //TestTimer();
        }

        private void form_Load(object sender, EventArgs e)
        {
            
        }


    }
}
